/*
* Copyright (c) 2025 Shenzhen Kaihong Digital Industry Development Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <cstdio>
#include <cmath>
#include <cfloat>
#include <string_view>

#include <catch2/catch_test_macros.hpp>
#include <catch2/catch_approx.hpp>
#include "../bincode/Decoder.h"
#include "../bincode/Encoder.h"
#define CATCH_CONFIG_MAIN

TEST_CASE("Test Put Functions", "[test_put]") {
    SECTION("Test Put bool") {
        OHOS::OHMW::DefaultEncoder encoder;
        std::vector<uint8_t> buffer;
        bool input = true;
        bool result = encoder.Put(buffer, input);
        REQUIRE(result);
        REQUIRE(buffer.size() == 1);
        REQUIRE(buffer[0] == 1);
    }

    SECTION("Test Put uint8_t") {
        OHOS::OHMW::DefaultEncoder encoder;
        std::vector<uint8_t> buffer;
        uint8_t input = 123;
        bool result = encoder.Put(buffer, input);
        REQUIRE(result);
        REQUIRE(buffer.size() == 1);
        REQUIRE(buffer[0] == 123);
    }

    SECTION("Test Put uint16_t") {
        OHOS::OHMW::DefaultEncoder encoder;
        std::vector<uint8_t> buffer;
        uint16_t input = 0x1234;
        bool result = encoder.Put(buffer, input);
        REQUIRE(result);
        REQUIRE(buffer.size() == 2);
        REQUIRE(buffer[0] == 0x34);
        REQUIRE(buffer[1] == 0x12);
    }

    SECTION("Test Put uint32_t") {
        OHOS::OHMW::DefaultEncoder encoder;
        std::vector<uint8_t> buffer;
        uint32_t input = 0x12345678;
        bool result = encoder.Put(buffer, input);

        REQUIRE(result);
        REQUIRE(buffer.size() == 4);
        REQUIRE(buffer[0] == 0x78);
        REQUIRE(buffer[1] == 0x56);
        REQUIRE(buffer[2] == 0x34);
        REQUIRE(buffer[3] == 0x12);
    }

    SECTION("Test Put uint64_t") {
        OHOS::OHMW::DefaultEncoder encoder;
        std::vector<uint8_t> buffer;
        uint64_t input = 0x1122334455667788;
        bool result = encoder.Put(buffer, input);

        REQUIRE(result);
        REQUIRE(buffer.size() == 8);
        REQUIRE(buffer[0] == 0x88);
        REQUIRE(buffer[1] == 0x77);
        REQUIRE(buffer[2] == 0x66);
        REQUIRE(buffer[3] == 0x55);
        REQUIRE(buffer[4] == 0x44);
        REQUIRE(buffer[5] == 0x33);
        REQUIRE(buffer[6] == 0x22);
        REQUIRE(buffer[7] == 0x11);
    }

    SECTION("Test Put int8_t") {
        OHOS::OHMW::DefaultEncoder encoder;
        std::vector<uint8_t> buffer;
        int8_t input = 123;
        bool result = encoder.Put(buffer, input);
        REQUIRE(result);
        REQUIRE(buffer.size() == 1);
        REQUIRE(buffer[0] == 123);
    }

    SECTION("Test Put int16_t") {
        OHOS::OHMW::DefaultEncoder encoder;
        std::vector<uint8_t> buffer;
        int16_t input = 0x1234;
        bool result = encoder.Put(buffer, input);
        REQUIRE(result);
        REQUIRE(buffer.size() == 2);
        REQUIRE(buffer[0] == 0x34);
        REQUIRE(buffer[1] == 0x12);
    }

    SECTION("Test Put int32_t") {
        OHOS::OHMW::DefaultEncoder encoder;
        std::vector<uint8_t> buffer;
        int32_t input = -12345678;
        bool result = encoder.Put(buffer, input);
        REQUIRE(result);
        REQUIRE(buffer.size() == 4);
        REQUIRE(buffer[0] == 0xB2);
        REQUIRE(buffer[1] == 0x9E);
        REQUIRE(buffer[2] == 0x43);
        REQUIRE(buffer[3] == 0xFF);
    }

    SECTION("Test Put int64_t") {
        OHOS::OHMW::DefaultEncoder encoder;
        std::vector<uint8_t> buffer;
        int64_t input = 0xFF439EB2;
        bool result = encoder.Put(buffer, input);
        REQUIRE(result);
        REQUIRE(buffer.size() == 8);
        REQUIRE(buffer[0] == 0xB2);
        REQUIRE(buffer[1] == 0x9E);
        REQUIRE(buffer[2] == 0x43);
        REQUIRE(buffer[3] == 0xFF);
        REQUIRE(buffer[4] == 0x00);
        REQUIRE(buffer[5] == 0x00);
        REQUIRE(buffer[6] == 0x00);
        REQUIRE(buffer[7] == 0x00);
    }

    SECTION("Test Put float") {
        OHOS::OHMW::DefaultEncoder encoder;
        std::vector<uint8_t> buffer;
        float input = 1.0;
        bool result = encoder.Put(buffer, input);
        REQUIRE(result);
        REQUIRE(buffer.size() == 4);
        REQUIRE(buffer[0] == 0x00);
        REQUIRE(buffer[1] == 0x00);
        REQUIRE(buffer[2] == 0x80);
        REQUIRE(buffer[3] == 0x3F);
    }

    SECTION("Test Put double") {
        OHOS::OHMW::DefaultEncoder encoder;
        std::vector<uint8_t> buffer;
        double input = 1.0;
        bool result = encoder.Put(buffer, input);
        REQUIRE(result);
        REQUIRE(buffer.size() == 8);
        REQUIRE(buffer[0] == 0x00);
        REQUIRE(buffer[1] == 0x00);
        REQUIRE(buffer[2] == 0x00);
        REQUIRE(buffer[3] == 0x00);
        REQUIRE(buffer[4] == 0x00);
        REQUIRE(buffer[5] == 0x00);
        REQUIRE(buffer[6] == 0xF0);
        REQUIRE(buffer[7] == 0x3F);
    }

    SECTION("Test Put str") {
        OHOS::OHMW::DefaultEncoder encoder;
        std::vector<uint8_t> buffer;
        std::string input = "Hello, world!";
        bool result = encoder.Put(buffer, input);
        REQUIRE(result);
        REQUIRE(buffer.size() == 17);
        REQUIRE(buffer[0] == 13);
        REQUIRE(buffer[1] == 0);
        REQUIRE(buffer[2] == 0);
        REQUIRE(buffer[3] == 0);
        REQUIRE(buffer[4] == 72);
        REQUIRE(buffer[5] == 101);
        REQUIRE(buffer[6] == 108);
        REQUIRE(buffer[7] == 108);
        REQUIRE(buffer[8] == 111);
        REQUIRE(buffer[9] == 44);
        REQUIRE(buffer[10] == 32);
        REQUIRE(buffer[11] == 119);
        REQUIRE(buffer[12] == 111);
        REQUIRE(buffer[13] == 114);
        REQUIRE(buffer[14] == 108);
        REQUIRE(buffer[15] == 100);
        REQUIRE(buffer[16] == 33);
    }

    SECTION("Test Put string_view") {
        OHOS::OHMW::DefaultEncoder encoder;
        std::vector<uint8_t> buffer;
        std::string_view input = "Hello, world!";
        bool result = encoder.Put(buffer, input);
        REQUIRE(result);
        REQUIRE(buffer.size() == 17);
        REQUIRE(buffer[0] == 13);
        REQUIRE(buffer[1] == 0);
        REQUIRE(buffer[2] == 0);
        REQUIRE(buffer[3] == 0);
        REQUIRE(buffer[4] == 72);
        REQUIRE(buffer[5] == 101);
        REQUIRE(buffer[6] == 108);
        REQUIRE(buffer[7] == 108);
        REQUIRE(buffer[8] == 111);
        REQUIRE(buffer[9] == 44);
        REQUIRE(buffer[10] == 32);
        REQUIRE(buffer[11] == 119);
        REQUIRE(buffer[12] == 111);
        REQUIRE(buffer[13] == 114);
        REQUIRE(buffer[14] == 108);
        REQUIRE(buffer[15] == 100);
        REQUIRE(buffer[16] == 33);
    }
}

TEST_CASE("Test Put Functions Unchecked", "[test_put_unchecked]") {
    SECTION("Test Put bool Unchecked") {
        OHOS::OHMW::DefaultEncoder encoder;
        std::vector<uint8_t> buffer(1, 0);
        bool input = true;
        encoder.PutUnchecked(buffer, input);
        REQUIRE(buffer.size() == 1);
        REQUIRE(buffer[0] == 1);
    }

    SECTION("Test Put uint8_t Unchecked") {
        OHOS::OHMW::DefaultEncoder encoder;
        std::vector<uint8_t> buffer(1, 0);
        uint8_t input = 123;
        encoder.PutUnchecked(buffer, input);
        REQUIRE(buffer.size() == 1);
        REQUIRE(buffer[0] == 123);
    }

    SECTION("Test Put uint16_t Unchecked") {
        OHOS::OHMW::DefaultEncoder encoder;
        std::vector<uint8_t> buffer(2, 0);
        uint16_t input = 0x1234;
        encoder.PutUnchecked(buffer, input);
        REQUIRE(buffer.size() == 2);
        REQUIRE(buffer[0] == 0x34);
        REQUIRE(buffer[1] == 0x12);
    }

    SECTION("Test Put uint32_t Unchecked") {
        OHOS::OHMW::DefaultEncoder encoder;
        std::vector<uint8_t> buffer(4, 0);
        uint32_t input = 0x12345678;
        encoder.PutUnchecked(buffer, input);
        REQUIRE(buffer.size() == 4);
        REQUIRE(buffer[0] == 0x78);
        REQUIRE(buffer[1] == 0x56);
        REQUIRE(buffer[2] == 0x34);
        REQUIRE(buffer[3] == 0x12);
    }

    SECTION("Test Put uint64_t Unchecked") {
        OHOS::OHMW::DefaultEncoder encoder;
        std::vector<uint8_t> buffer(8, 0);
        uint64_t input = 0x1122334455667788;
        encoder.PutUnchecked(buffer, input);
        REQUIRE(buffer.size() == 8);
        REQUIRE(buffer[0] == 0x88);
        REQUIRE(buffer[1] == 0x77);
        REQUIRE(buffer[2] == 0x66);
        REQUIRE(buffer[3] == 0x55);
        REQUIRE(buffer[4] == 0x44);
        REQUIRE(buffer[5] == 0x33);
        REQUIRE(buffer[6] == 0x22);
        REQUIRE(buffer[7] == 0x11);
    }

    SECTION("Test Put int8_t Unchecked") {
        OHOS::OHMW::DefaultEncoder encoder;
        std::vector<uint8_t> buffer(1, 0);
        int8_t input = 123;
        encoder.PutUnchecked(buffer, input);
        REQUIRE(buffer.size() == 1);
        REQUIRE(buffer[0] == 123);
    }

    SECTION("Test Put int16_t Unchecked") {
        OHOS::OHMW::DefaultEncoder encoder;
        std::vector<uint8_t> buffer(2, 0);
        int16_t input = 0x1234;
        encoder.PutUnchecked(buffer, input);
        REQUIRE(buffer.size() == 2);
        REQUIRE(buffer[0] == 0x34);
        REQUIRE(buffer[1] == 0x12);
    }

    SECTION("Test Put int32_t Unchecked") {
        OHOS::OHMW::DefaultEncoder encoder;
        std::vector<uint8_t> buffer(4, 0);
        int32_t input = -12345678;
        encoder.PutUnchecked(buffer, input);
        REQUIRE(buffer.size() == 4);
        REQUIRE(buffer[0] == 0xB2);
        REQUIRE(buffer[1] == 0x9E);
        REQUIRE(buffer[2] == 0x43);
        REQUIRE(buffer[3] == 0xFF);
    }

    SECTION("Test Put int64_t Unchecked") {
        OHOS::OHMW::DefaultEncoder encoder;
        std::vector<uint8_t> buffer(8, 0);
        int64_t input = 0xFF439EB2;
        encoder.PutUnchecked(buffer, input);
        REQUIRE(buffer.size() == 8);
        REQUIRE(buffer[0] == 0xB2);
        REQUIRE(buffer[1] == 0x9E);
        REQUIRE(buffer[2] == 0x43);
        REQUIRE(buffer[3] == 0xFF);
        REQUIRE(buffer[4] == 0x00);
        REQUIRE(buffer[5] == 0x00);
        REQUIRE(buffer[6] == 0x00);
        REQUIRE(buffer[7] == 0x00);
    }

    SECTION("Test Put float Unchecked") {
        OHOS::OHMW::DefaultEncoder encoder;
        std::vector<uint8_t> buffer(4, 0);
        float input = 1.0;
        encoder.PutUnchecked(buffer, input);
        REQUIRE(buffer.size() == 4);
        REQUIRE(buffer[0] == 0x00);
        REQUIRE(buffer[1] == 0x00);
        REQUIRE(buffer[2] == 0x80);
        REQUIRE(buffer[3] == 0x3F);
    }

    SECTION("Test Put double Unchecked") {
        OHOS::OHMW::DefaultEncoder encoder;
        std::vector<uint8_t> buffer(8, 0);
        double input = 1.0;
        encoder.PutUnchecked(buffer, input);
        REQUIRE(buffer.size() == 8);
        REQUIRE(buffer[0] == 0x00);
        REQUIRE(buffer[1] == 0x00);
        REQUIRE(buffer[2] == 0x00);
        REQUIRE(buffer[3] == 0x00);
        REQUIRE(buffer[4] == 0x00);
        REQUIRE(buffer[5] == 0x00);
        REQUIRE(buffer[6] == 0xF0);
        REQUIRE(buffer[7] == 0x3F);
    }

    SECTION("Test Put str Unchecked") {
        OHOS::OHMW::DefaultEncoder encoder;
        std::vector<uint8_t> buffer(17, 0);
        std::string input = "Hello, world!";
        encoder.PutUnchecked(buffer, input);
        REQUIRE(buffer.size() == 17);
        REQUIRE(buffer[0] == 13);
        REQUIRE(buffer[1] == 0);
        REQUIRE(buffer[2] == 0);
        REQUIRE(buffer[3] == 0);
        REQUIRE(buffer[4] == 72);
        REQUIRE(buffer[5] == 101);
        REQUIRE(buffer[6] == 108);
        REQUIRE(buffer[7] == 108);
        REQUIRE(buffer[8] == 111);
        REQUIRE(buffer[9] == 44);
        REQUIRE(buffer[10] == 32);
        REQUIRE(buffer[11] == 119);
        REQUIRE(buffer[12] == 111);
        REQUIRE(buffer[13] == 114);
        REQUIRE(buffer[14] == 108);
        REQUIRE(buffer[15] == 100);
        REQUIRE(buffer[16] == 33);
    }

    SECTION("Test Put string_view Unchecked") {
        OHOS::OHMW::DefaultEncoder encoder;
        std::vector<uint8_t> buffer(17, 0);
        std::string_view input = "Hello, world!";
        encoder.PutUnchecked(buffer, input);
        REQUIRE(buffer.size() == 17);
        REQUIRE(buffer[0] == 13);
        REQUIRE(buffer[1] == 0);
        REQUIRE(buffer[2] == 0);
        REQUIRE(buffer[3] == 0);
        REQUIRE(buffer[4] == 72);
        REQUIRE(buffer[5] == 101);
        REQUIRE(buffer[6] == 108);
        REQUIRE(buffer[7] == 108);
        REQUIRE(buffer[8] == 111);
        REQUIRE(buffer[9] == 44);
        REQUIRE(buffer[10] == 32);
        REQUIRE(buffer[11] == 119);
        REQUIRE(buffer[12] == 111);
        REQUIRE(buffer[13] == 114);
        REQUIRE(buffer[14] == 108);
        REQUIRE(buffer[15] == 100);
        REQUIRE(buffer[16] == 33);
    }
}

TEST_CASE("Test Get Functions", "[test_get]") {
    SECTION("Test Get bool") {
        OHOS::OHMW::DefaultDecoder decoder;
        std::vector<uint8_t> buffer = {1};
        bool value;
        bool result = decoder.Get(buffer, value);
        REQUIRE(result);
        REQUIRE(value);
    }

    SECTION("Test Get uint8_t") {
        OHOS::OHMW::DefaultDecoder decoder;
        std::vector<uint8_t> buffer = {123};
        uint8_t value;
        bool result = decoder.Get(buffer, value);
        REQUIRE(result);
        REQUIRE(value == 123);
    }

    SECTION("Test Get uint16_t") {
        OHOS::OHMW::DefaultDecoder decoder;
        std::vector<uint8_t> buffer = {0x34, 0x12};
        uint16_t value;
        bool result = decoder.Get(buffer, value);
        REQUIRE(result);
        REQUIRE(value == 0x1234);
    }

    SECTION("Test Get uint32_t") {
        OHOS::OHMW::DefaultDecoder decoder;
        std::vector<uint8_t> buffer = {0x78, 0x56, 0x34, 0x12};
        uint32_t value;
        bool result = decoder.Get(buffer, value);
        REQUIRE(result);
        REQUIRE(value == 0x12345678);
    }

    SECTION("Test Get uint32_t with offset") {
        OHOS::OHMW::DefaultDecoder decoder(1);
        std::vector<uint8_t> buffer = {0x00, 0x78, 0x56, 0x34, 0x12};
        uint32_t value;
        bool result = decoder.Get(buffer, value);
        REQUIRE(result);
        REQUIRE(value == 0x12345678);
    }

    SECTION("Test Get uint64_t") {
        OHOS::OHMW::DefaultDecoder decoder;
        std::vector<uint8_t> buffer = {0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11};
        uint64_t value;
        bool result = decoder.Get(buffer, value);
        REQUIRE(result);
        REQUIRE(value == 0x1122334455667788);
    }

    SECTION("Test Get int8_t") {
        OHOS::OHMW::DefaultDecoder decoder;
        std::vector<uint8_t> buffer = {123};
        int8_t value;
        bool result = decoder.Get(buffer, value);
        REQUIRE(result);
        REQUIRE(value == 123);
    }

    SECTION("Test Get int16_t") {
        OHOS::OHMW::DefaultDecoder decoder;
        std::vector<uint8_t> buffer = {0x34, 0x12};
        int16_t value;
        bool result = decoder.Get(buffer, value);
        REQUIRE(result);
        REQUIRE(value == 0x1234);
    }

    SECTION("Test Get int32_t") {
        OHOS::OHMW::DefaultDecoder decoder;
        std::vector<uint8_t> buffer = {0xB2, 0x9E, 0x43, 0xFF};
        int32_t value;
        bool result = decoder.Get(buffer, value);
        REQUIRE(result);
        REQUIRE(value == -12345678);
    }

    SECTION("Test Get int64_t") {
        OHOS::OHMW::DefaultDecoder decoder;
        std::vector<uint8_t> buffer = {0xB2, 0x9E, 0x43, 0xFF, 0x00, 0x00, 0x00, 0x00};
        int64_t value;
        bool result = decoder.Get(buffer, value);
        REQUIRE(result);
        REQUIRE(value == 0xFF439EB2);
    }

    SECTION("Test Get float") {
        OHOS::OHMW::DefaultDecoder decoder;
        std::vector<uint8_t> buffer = {0x00, 0x00, 0x80, 0x3F};
        float value;
        bool result = decoder.Get(buffer, value);
        REQUIRE(result);
        REQUIRE(value == Catch::Approx(1.0f));
    }

    SECTION("Test Get double") {
        OHOS::OHMW::DefaultDecoder decoder;
        std::vector<uint8_t> buffer = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F};
        double value;
        bool result = decoder.Get(buffer, value);
        REQUIRE(result);
        REQUIRE(value == Catch::Approx(1.0));
    }

    SECTION("Test Get str") {
        OHOS::OHMW::DefaultDecoder decoder;
        std::vector<uint8_t> buffer = {13, 0, 0, 0, 72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33};
        std::string value;
        bool result = decoder.Get(buffer, value);
        REQUIRE(result);
        REQUIRE(value == "Hello, world!");
    }
}

TEST_CASE("Test Get Functions Unchecked", "[test_get_unchecked]") {
    SECTION("Test Get bool Unchecked") {
        OHOS::OHMW::DefaultDecoder decoder;
        std::vector<uint8_t> buffer = {1};
        bool value;
        decoder.GetUnchecked(buffer, value);
        REQUIRE(value);
    }

    SECTION("Test Get uint8_t Unchecked") {
        OHOS::OHMW::DefaultDecoder decoder;
        std::vector<uint8_t> buffer = {123};
        uint8_t value;
        decoder.GetUnchecked(buffer, value);
        REQUIRE(value == 123);
    }

    SECTION("Test Get uint16_t Unchecked") {
        OHOS::OHMW::DefaultDecoder decoder;
        std::vector<uint8_t> buffer = {0x34, 0x12};
        uint16_t value;
        decoder.GetUnchecked(buffer, value);
        REQUIRE(value == 0x1234);
    }

    SECTION("Test Get uint32_t Unchecked") {
        OHOS::OHMW::DefaultDecoder decoder;
        std::vector<uint8_t> buffer = {0x78, 0x56, 0x34, 0x12};
        uint32_t value;
        decoder.GetUnchecked(buffer, value);
        REQUIRE(value == 0x12345678);
    }

    SECTION("Test Get uint64_t Unchecked") {
        OHOS::OHMW::DefaultDecoder decoder;
        std::vector<uint8_t> buffer = {0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11};
        uint64_t value;
        decoder.GetUnchecked(buffer, value);
        REQUIRE(value == 0x1122334455667788);
    }

    SECTION("Test Get int8_t Unchecked") {
        OHOS::OHMW::DefaultDecoder decoder;
        std::vector<uint8_t> buffer = {123};
        int8_t value;
        decoder.GetUnchecked(buffer, value);
        REQUIRE(value == 123);
    }

    SECTION("Test Get int16_t Unchecked") {
        OHOS::OHMW::DefaultDecoder decoder;
        std::vector<uint8_t> buffer = {0x34, 0x12};
        int16_t value;
        decoder.GetUnchecked(buffer, value);
        REQUIRE(value == 0x1234);
    }

    SECTION("Test Get int32_t Unchecked") {
        OHOS::OHMW::DefaultDecoder decoder;
        std::vector<uint8_t> buffer = {0xB2, 0x9E, 0x43, 0xFF};
        int32_t value;
        decoder.GetUnchecked(buffer, value);
        REQUIRE(value == -12345678);
    }

    SECTION("Test Get int64_t Unchecked") {
        OHOS::OHMW::DefaultDecoder decoder;
        std::vector<uint8_t> buffer = {0xB2, 0x9E, 0x43, 0xFF, 0x00, 0x00, 0x00, 0x00};
        int64_t value;
        decoder.GetUnchecked(buffer, value);
        REQUIRE(value == 0xFF439EB2);
    }

    SECTION("Test Get float Unchecked") {
        OHOS::OHMW::DefaultDecoder decoder;
        std::vector<uint8_t> buffer = {0x00, 0x00, 0x80, 0x3F};
        float value;
        decoder.GetUnchecked(buffer, value);
        REQUIRE(value == Catch::Approx(1.0f));
    }

    SECTION("Test Get double Unchecked") {
        OHOS::OHMW::DefaultDecoder decoder;
        std::vector<uint8_t> buffer = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F};
        double value;
        decoder.GetUnchecked(buffer, value);
        REQUIRE(value == Catch::Approx(1.0));
    }

    SECTION("Test Get str Unchecked") {
        OHOS::OHMW::DefaultDecoder decoder;
        std::vector<uint8_t> buffer = {13, 0, 0, 0, 72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33};
        std::string value;
        decoder.GetUnchecked(buffer, value);
        REQUIRE(value == "Hello, world!");
    }
}